﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace 进程通讯.服务端
{
    interface ISocketServer
    {
        bool Listen(string ip,int prot);
        void Close();
        void Send(EndPoint endPoint, byte[] data);
    }

    public class SocketServer:ISocketServer
    {
        public Socket ServerSocket;
        public bool IsStop=false;
        public Dictionary<EndPoint, Socket> Clients=new Dictionary<EndPoint, Socket>();
        public int ReceiveBufferSize { get; set; }=1024;
        public event Action<EndPoint, byte[]> Receive;


        public void Close()
        {
            try
            {
                IsStop= true;
                if (Clients.Count>0)
                {
                    foreach (var item in Clients.Keys)
                    {
                        Clients[item]?.Shutdown(SocketShutdown.Both);
                        Clients[item]?.Close();
                    }
                }
                Task.WaitAll();
                ServerSocket?.Close();
                ServerSocket = null;
            }
            catch
            {

            }
        }

        public bool Listen(string ip, int prot)
        {
            try
            {
                ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                ServerSocket.Bind(new IPEndPoint(IPAddress.Parse(ip), prot));
                ServerSocket.Listen(1000);
                Task.Run(Accept);
                return true;
            }
            catch
            {

            }
            return false;
        }

        public void Send(EndPoint endPoint, byte[] data)
        {
            try
            {
                if (Clients.ContainsKey(endPoint))
                {
                    Clients[endPoint].Send(data);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        private async Task Accept()
        {
            while(!IsStop)
            {
                //Socket SocketLisent=ServerSocket?.Accept();
                //if (SocketLisent == null) continue;
                //EndPoint ep = SocketLisent.RemoteEndPoint;
                //if(!Clients.ContainsKey(ep)) Clients.Add(ep, SocketLisent);
                //Task.Factory.StartNew(ClientData, SocketLisent);
                Socket SocketLisent = await Task.Run(() => ServerSocket?.Accept());
                if (SocketLisent == null) continue;
                EndPoint ep = SocketLisent.RemoteEndPoint;
                if (!Clients.ContainsKey(ep)) Clients.Add(ep, SocketLisent);
                _ = Task.Run(() => ClientData(SocketLisent));
            };
        }

        private void ClientData(object obj)
        {
            Socket client=obj as Socket;
            if (client == null) return;
            EndPoint ep = client.RemoteEndPoint;
            try
            {
                while (!IsStop)
                {
                    if (client.Available <= 0) continue;
                    byte[] buffer = new byte[ReceiveBufferSize];
                    int len = client.Receive(buffer);
                    if (len <= 0) break;
                    byte[] data= buffer.Take(len).ToArray();
                    try
                    {
                        Receive?.Invoke(ep, data);
                    }
                    catch
                    {
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            if (Clients.ContainsKey(ep)) Clients.Remove(ep);
        }
    }
}
